package com.hys.app.service.erp.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hys.app.framework.database.WebPage;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.util.BeanUtil;
import com.hys.app.framework.util.DateUtil;
import com.hys.app.framework.util.PageConvert;
import com.hys.app.framework.util.StringUtil;
import com.hys.app.mapper.erp.StockInventoryMapper;
import com.hys.app.model.erp.dos.StockInventory;
import com.hys.app.model.erp.dos.StockInventoryProduct;
import com.hys.app.model.erp.dto.StockInventoryDTO;
import com.hys.app.model.erp.dto.StockInventoryParam;
import com.hys.app.model.erp.enums.NoBusinessTypeEnum;
import com.hys.app.model.erp.enums.StockInventoryStatusEnum;
import com.hys.app.model.erp.vo.StockInventoryAllowable;
import com.hys.app.model.erp.vo.StockInventoryVO;
import com.hys.app.model.system.dos.AdminUser;
import com.hys.app.service.erp.NoGenerateManager;
import com.hys.app.service.erp.StockInventoryManager;
import com.hys.app.service.erp.StockInventoryProductManager;
import com.hys.app.service.system.AdminUserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 库存盘点单业务接口实现
 *
 * @author dmy
 * 2023-12-05
 */
@Service
public class StockInventoryManagerImpl extends ServiceImpl<StockInventoryMapper, StockInventory> implements StockInventoryManager {

    @Autowired
    private NoGenerateManager noGenerateManager;

    @Autowired
    private StockInventoryProductManager stockInventoryProductManager;

    @Autowired
    private AdminUserManager adminUserManager;

    /**
     * 查询库存盘点单分页列表数据
     *
     * @param params 查询参数
     * @return
     */
    @Override
    public WebPage list(StockInventoryParam params) {
        IPage<StockInventory> iPage = this.lambdaQuery()
                .like(StringUtil.notEmpty(params.getSn()), StockInventory::getSn, params.getSn())
                .like(StringUtil.notEmpty(params.getInventoryPerson()), StockInventory::getInventoryPerson, params.getInventoryPerson())
                .eq(params.getWarehouseId() != null, StockInventory::getWarehouseId, params.getWarehouseId())
                .eq(StringUtil.notEmpty(params.getStatus()), StockInventory::getStatus, params.getStatus())
                .eq(params.getDeptId() != null, StockInventory::getDeptId, params.getDeptId())
                .gt(params.getStartTime() != null, StockInventory::getInventoryTime, params.getStartTime())
                .lt(params.getEndTime() != null, StockInventory::getInventoryTime, params.getEndTime())
                .orderByDesc(StockInventory::getCreateTime)
                .page(new Page<>(params.getPageNo(), params.getPageSize()));

        for (StockInventory record : iPage.getRecords()) {
            StockInventoryAllowable allowable = new StockInventoryAllowable(record);
            record.setAllowable(allowable);
        }
        return PageConvert.convert(iPage);
    }

    /**
     * 新增库存盘点单
     *
     * @param stockInventoryDTO 库存盘点单信息
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void add(StockInventoryDTO stockInventoryDTO) {
        //构建盘点单信息
        StockInventory stockInventory = new StockInventory();
        BeanUtil.copyProperties(stockInventoryDTO, stockInventory);
        //生成库存盘点单编号
        String sn = noGenerateManager.generate(NoBusinessTypeEnum.StockInventory);
        stockInventory.setSn(sn);
        //设置创建时间
        stockInventory.setCreateTime(DateUtil.getDateline());
        //设置状态默认为未提交（待审核）
        stockInventory.setStatus(StockInventoryStatusEnum.NEW.name());
        //入库
        this.save(stockInventory);
        //获取主键ID
        Long id = stockInventory.getId();
        //保存库存盘点单商品信息
        this.stockInventoryProductManager.saveProduct(id, stockInventoryDTO.getProductList());
    }

    /**
     * 编辑库存盘点单
     *
     * @param id 主键ID
     * @param stockInventoryDTO 库存盘点单信息
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void edit(Long id, StockInventoryDTO stockInventoryDTO) {
        //获取库存盘点单旧数据
        StockInventory stockInventory  = this.getById(id);
        if (!StockInventoryStatusEnum.NEW.name().equals(stockInventory.getStatus())
                && !StockInventoryStatusEnum.REJECT.name().equals(stockInventory.getStatus())) {
            throw new ServiceException("只有状态为未提交或审核驳回的库存盘点单才可以进行编辑操作");
        }
        //复制修改后的数据
        BeanUtil.copyProperties(stockInventoryDTO, stockInventory);
        //编辑后默认库存盘点单状态为未提交（待审核）
        stockInventory.setStatus(StockInventoryStatusEnum.NEW.name());
        //修改库存盘点单信息
        this.updateById(stockInventory);
        //入库库存报损单商品
        this.stockInventoryProductManager.saveProduct(id, stockInventoryDTO.getProductList());
    }

    /**
     * 删除库存盘点单
     *
     * @param ids 库存盘点单主键ID集合
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void delete(List<Long> ids) {
        List<StockInventory> inventories = this.lambdaQuery()
                .in(StockInventory::getId, ids)
                .list();
        if (inventories == null || inventories.size() == 0) {
            throw new ServiceException("要删除的库存盘点单不存在");
        }
        //验证库存盘点单状态是否可以删除
        for (StockInventory inventory : inventories) {
            if (!StockInventoryStatusEnum.NEW.name().equals(inventory.getStatus())
                    && !StockInventoryStatusEnum.REJECT.name().equals(inventory.getStatus())) {
                throw new ServiceException("只有状态为未提交或审核驳回的库存盘点单才可进行删除操作");
            }
        }
        //批量删除库存盘点单
        this.removeByIds(ids);
        //删除库存盘点单商品信息
        this.stockInventoryProductManager.deleteProduct(ids);
    }

    /**
     * 获取库存盘点单详情
     *
     * @param id 主键ID
     * @return
     */
    @Override
    public StockInventoryVO getDetail(Long id) {
        StockInventory stockInventory = this.getById(id);
        StockInventoryVO stockInventoryVO = new StockInventoryVO();
        BeanUtil.copyProperties(stockInventory, stockInventoryVO);

        //获取库存盘点单商品信息
        List<StockInventoryProduct> goodsList = this.stockInventoryProductManager.list(id);
        stockInventoryVO.setProductList(goodsList);
        return stockInventoryVO;
    }

    /**
     * 库存盘点单提交审核
     *
     * @param ids 库存盘点单主键ID集合
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void submit(List<Long> ids) {
        List<StockInventory> inventories = this.lambdaQuery()
                .in(StockInventory::getId, ids)
                .list();
        if (inventories == null || inventories.size() == 0) {
            throw new ServiceException("要提交审核的库存盘点单不存在");
        }
        //验证库存盘点单状态是否可以提交审核
        for (StockInventory inventory : inventories) {
            if (!StockInventoryStatusEnum.NEW.name().equals(inventory.getStatus())) {
                throw new ServiceException("只有状态为未提交的库存盘点单才可进行提交审核操作");
            }
        }
        //将库存盘点单状态修改为已提交（待审核）
        this.lambdaUpdate()
                .set(StockInventory::getStatus, StockInventoryStatusEnum.WAIT.name())
                .in(StockInventory::getId, ids)
                .update();
    }

    /**
     * 库存盘点单撤销提交审核
     *
     * @param ids 库存盘点单主键ID集合
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void cancel(List<Long> ids) {
        List<StockInventory> inventories = this.lambdaQuery()
                .in(StockInventory::getId, ids)
                .list();
        if (inventories == null || inventories.size() == 0) {
            throw new ServiceException("要撤销提交审核的库存盘点单不存在");
        }
        //验证库存盘点单状态是否可以撤销提交
        for (StockInventory inventory : inventories) {
            if (!StockInventoryStatusEnum.WAIT.name().equals(inventory.getStatus())) {
                throw new ServiceException("只有状态为已提交的库存盘点单才可进行撤销操作");
            }
        }
        //将库存盘点单状态修改为未提交
        this.lambdaUpdate()
                .set(StockInventory::getStatus, StockInventoryStatusEnum.NEW.name())
                .in(StockInventory::getId, ids)
                .update();
    }

    /**
     * 审核库存盘点单
     *
     * @param ids 库存盘点单ID集合
     * @param status 审核状态 PASS：审核通过，REJECT：审核驳回
     * @param rejectReason 驳回原因
     */
    @Override
    @Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void audit(List<Long> ids, String status, String rejectReason) {
        List<StockInventory> inventories = this.lambdaQuery()
                .in(StockInventory::getId, ids)
                .list();
        if (inventories == null || inventories.size() == 0) {
            throw new ServiceException("要进行审核的库存盘点单不存在");
        }
        if (!StockInventoryStatusEnum.PASS.name().equals(status)
                && !StockInventoryStatusEnum.REJECT.name().equals(status)) {
            throw new ServiceException("审核状态不正确");
        }
        if (StockInventoryStatusEnum.REJECT.name().equals(status)) {
            if (StringUtil.isEmpty(rejectReason)) {
                throw new ServiceException("请填写审核驳回原因");
            }
            if (rejectReason.length() > 200) {
                throw new ServiceException("驳回原因不能超过200个字符");
            }
        }
        //获取当前登录管理员
        AdminUser adminUser = this.adminUserManager.getCurrUser();
        //循环审核库存盘点单
        for (StockInventory inventory : inventories) {
            if (!StockInventoryStatusEnum.WAIT.name().equals(inventory.getStatus())) {
                throw new ServiceException("只有状态为待审核的库存盘点单才可以进行审核操作");
            }
        }
        //修改库存盘点单状态
        this.lambdaUpdate()
                .set(StockInventory::getStatus, status)
                .set(StringUtil.notEmpty(rejectReason), StockInventory::getRejectReason, rejectReason)
                .set(StockInventory::getAuditTime, DateUtil.getDateline())
                .set(StockInventory::getAuditPersonId, adminUser.getId())
                .set(StockInventory::getAuditPersonName, adminUser.getRealName())
                .in(StockInventory::getId, ids)
                .update();
    }
}
